package com.allen.study.domain.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.allen.study.common.base.DomainResponse;
import com.allen.study.common.constants.LeaveApplyConstants;
import com.allen.study.common.exception.CamundaProcessException;
import com.allen.study.common.utils.CamundaUtils;
import com.allen.study.domain.entity.ApprovalRecord;
import com.allen.study.domain.entity.LeaveApply;
import com.allen.study.domain.entity.LeaveApplyApprove;
import com.allen.study.domain.repository.IApprovalRecordRepo;
import com.allen.study.domain.repository.ILeaveApplyRepo;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.camunda.bpm.engine.repository.Deployment;
import org.camunda.bpm.engine.task.Task;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

import static com.allen.study.common.constants.LeaveApplyConstants.processDefinitionKey;

/**
 * 请假申请表领域服务
 *
 * @author AllenSun
 * @since 2025-04-23 20:46
 */
@Service
@AllArgsConstructor
@Slf4j
public class LeaveApplyService {

    /**
     * 请假申请表资源库
     */
    private final ILeaveApplyRepo leaveApplyRepo;

    private final IApprovalRecordRepo approvalRecordRepo;

    /**
     * 创建请假申请表
     *
     * @param leaveApply 请假申请表实体
     * @return 响应结果
     */
    public DomainResponse<Void> create(@NotNull LeaveApply leaveApply) {
        // 获取当前登录用户
        // SecurityUser securityUser = SecurityUserHelper.get();
        // 设置租户
        // leaveApply.setTenantId(securityUser.getTenantId());

        // 保存请假申请表
        leaveApplyRepo.create(leaveApply);
        return DomainResponse.ok();
    }

    /**
     * 根据主键删除请假申请表
     *
     * @param leaveApplyId 请假申请表主键
     * @return 响应结果
     */
    public DomainResponse<Void> deleteById(@NotNull Long leaveApplyId) {
        // 根据主键查询请假申请表
        LeaveApply leaveApply = leaveApplyRepo.queryById(leaveApplyId);
        // 请假申请表数据存在且租户正确，删除请假申请表数据
        if (ObjectUtils.isNotEmpty(leaveApply) && leaveApply.checkTenant()) {
            leaveApplyRepo.deleteById(leaveApplyId);
        }
        return DomainResponse.ok();
    }

    /**
     * 根据主键更新请假申请表
     *
     * @param leaveApply 请假申请表实体
     * @return 响应结果
     */
    public DomainResponse<Void> updateById(@NotNull LeaveApply leaveApply) {
        // 根据主键查询请假申请表
        LeaveApply exists = leaveApplyRepo.queryById(leaveApply.getId());
        // 请假申请表数据存在且租户正确，更新请假申请表数据
        if (ObjectUtils.isNotEmpty(exists) && exists.checkTenant()) {
            leaveApplyRepo.updateById(leaveApply);
        }
        return DomainResponse.ok();
    }

    /**
     * 根据主键查询请假申请表
     *
     * @param leaveApplyId 请假申请表主键
     * @return 响应结果
     */
    public DomainResponse<LeaveApply> queryById(@NotNull Long leaveApplyId) {
        LeaveApply leaveApply = leaveApplyRepo.queryById(leaveApplyId);
        return DomainResponse.ok(leaveApply);
    }

    public DomainResponse<LeaveApply> apply(@NotNull LeaveApply leaveApply) {

        leaveApply.setStatus("待审批");
        String employeeId = leaveApply.getEmployeeId();

        // 启动 Camunda 流程
        // 发起人填写的请假单
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> applyVariables = objectMapper.convertValue(leaveApply,Map.class);
        String processInstanceId = CamundaUtils.startProcessInstance(processDefinitionKey, applyVariables);
        log.info("请假流程启动成功");

        // 查询发起人在本次流程中的待办任务
        // List<Task> tasksByAssignee = CamundaUtils.getTasksByAssignee(employeeId, 1, 10);
        List<Task> tasksByAssignee = CamundaUtils.getTasksByAssigneeAndProcess(employeeId, processInstanceId,1, 10);
        if(ObjectUtil.isEmpty(tasksByAssignee)){
            throw new CamundaProcessException(employeeId+"没有待处理任务");
        }
        String taskId = tasksByAssignee.get(0).getId();
        CamundaUtils.completeTask(taskId,applyVariables);

        // 保存请假申请信息到数据库
        leaveApply.setProcessInstanceId(processInstanceId);
        leaveApplyRepo.create(leaveApply);
        log.info("请假信息存储成功");

        return DomainResponse.ok(leaveApply);
    }

    // public DomainResponse<PageResponseVO<LeaveApplyVO>> getMyApplyList(PageRequestDTO dto) {
    //     // try {
    //     //
    //     // } catch (Exception e) {
    //     //     log.error("分页查询我发起的申请信息列表失败", e);
    //     //     throw new LeaveApprovalException(500, "查询失败，请稍后重试");
    //     // }
    //     Page<LeaveApply> page = new Page<>(dto.getPageNum(), dto.getPageSize());
    //     QueryWrapper<LeaveApply> wrapper = new QueryWrapper<>();
    //     wrapper.eq("employee_id", dto.getApplicantId());
    //     IPage<LeaveApply> leaveApplyPage = leaveApplyMapper.selectPage(page, wrapper);
    //
    //     List<LeaveApplyVO> leaveApplyVOs = leaveApplyPage.getRecords().stream()
    //             .map(leaveApply -> modelMapper.map(leaveApply, LeaveApplyVO.class))
    //             .collect(Collectors.toList());
    //
    //     PageResponseVO<LeaveApplyVO> responseVO = new PageResponseVO<>();
    //     responseVO.setRecords(leaveApplyVOs);
    //     responseVO.setTotal(leaveApplyPage.getTotal());
    //     responseVO.setPageNum(dto.getPageNum());
    //     responseVO.setPageSize(dto.getPageSize());
    //     return DomainResponse.ok(responseVO);
    // }
    //
    // public DomainResponse<ApprovalProgressVO> getApprovalProgress(String processInstanceId) {
    //     // try {
    //     //
    //     // } catch (Exception e) {
    //     //     log.error("查看当前申请所有审批节点的进度和结果失败", e);
    //     //     throw new LeaveApprovalException(500, "查询进度失败，请稍后重试");
    //     // }
    //     ApprovalProgressVO progressVO = new ApprovalProgressVO();
    //     progressVO.setProcessInstanceId(processInstanceId);
    //
    //     List<HistoricActivityInstance> activityInstances = CamundaUtils.getHistoricActivityInstances(processInstanceId);
    //     List<ApprovalProgressVO.NodeProgress> nodeProgresses = new ArrayList<>();
    //
    //     for (HistoricActivityInstance instance : activityInstances) {
    //         ApprovalProgressVO.NodeProgress nodeProgress = new ApprovalProgressVO.NodeProgress();
    //         nodeProgress.setNodeName(instance.getActivityName());
    //         nodeProgress.setApproverId((String) instance.getAssignee());
    //         nodeProgress.setStatus(instance.getEndTime() != null? "已完成" : "待处理");
    //
    //         // 这里简单模拟审批结果和理由获取，实际可从流程变量或其他地方获取
    //         if (instance.getEndTime() != null) {
    //             nodeProgress.setApproved(true); // 假设通过
    //             nodeProgress.setReason("审批通过");
    //         }
    //         nodeProgresses.add(nodeProgress);
    //     }
    //
    //     progressVO.setNodeProgresses(nodeProgresses);
    //     return DomainResponse.ok(progressVO);
    // }
    //
    // public DomainResponse<PageResponseVO<LeaveApplyVO>> getPendingApprovalList(PageRequestDTO dto) {
    //     // try {
    //     //
    //     // } catch (Exception e) {
    //     //     log.error("分页查看我待审批的申请信息列表失败", e);
    //     //     throw new LeaveApprovalException(500, "查询待审批列表失败，请稍后重试");
    //     // }
    //     List<Task> tasks = CamundaUtils.getTasksByAssignee(dto.getApplicantId(), dto.getPageNum(), dto.getPageSize());
    //     List<LeaveApplyVO> leaveApplyVOs = new ArrayList<>();
    //
    //     for (Task task : tasks) {
    //         QueryWrapper<LeaveApply> wrapper = new QueryWrapper<>();
    //         wrapper.eq("process_instance_id", task.getProcessInstanceId());
    //         LeaveApply leaveApply = leaveApplyMapper.selectOne(wrapper);
    //         if (leaveApply != null) {
    //             leaveApplyVOs.add(modelMapper.map(leaveApply, LeaveApplyVO.class));
    //         }
    //     }
    //
    //     long total = CamundaUtils.getTasksByAssignee(dto.getApplicantId(), 1, Integer.MAX_VALUE).size();
    //
    //     PageResponseVO<LeaveApplyVO> responseVO = new PageResponseVO<>();
    //     responseVO.setRecords(leaveApplyVOs);
    //     responseVO.setTotal(total);
    //     responseVO.setPageNum(dto.getPageNum());
    //     responseVO.setPageSize(dto.getPageSize());
    //     return DomainResponse.ok(responseVO);
    // }
    //
    // public DomainResponse<PageResponseVO<LeaveApplyVO>> getApprovedList(PageRequestDTO dto) {
    //     List<org.camunda.bpm.engine.history.HistoricTaskInstance> completedTasks = CamundaUtils.getCompletedTasksByAssignee(dto.getApplicantId(), dto.getPageNum(), dto.getPageSize());
    //     List<LeaveApplyVO> leaveApplyVOs = new ArrayList<>();
    //
    //     for (org.camunda.bpm.engine.history.HistoricTaskInstance task : completedTasks) {
    //         QueryWrapper<LeaveApply> wrapper = new QueryWrapper<>();
    //         wrapper.eq("process_instance_id", task.getProcessInstanceId());
    //         LeaveApply leaveApply = leaveApplyMapper.selectOne(wrapper);
    //         if (leaveApply != null) {
    //             leaveApplyVOs.add(modelMapper.map(leaveApply, LeaveApplyVO.class));
    //         }
    //     }
    //
    //     long total = CamundaUtils.getCompletedTasksByAssignee(dto.getApplicantId(), 1, Integer.MAX_VALUE).size();
    //
    //     PageResponseVO<LeaveApplyVO> responseVO = new PageResponseVO<>();
    //     responseVO.setRecords(leaveApplyVOs);
    //     responseVO.setTotal(total);
    //     responseVO.setPageNum(dto.getPageNum());
    //     responseVO.setPageSize(dto.getPageSize());
    //     return DomainResponse.success(responseVO);
    // }
    //
    public DomainResponse<Void> approve(LeaveApplyApprove leaveApplyApprove) {
        // 审批记录
        ApprovalRecord approvalRecord = new ApprovalRecord();
        approvalRecord.setApproverId(leaveApplyApprove.getApproverId());
        approvalRecord.setApprovalResult(leaveApplyApprove.getApprovalResult());
        approvalRecord.setApprovalTime(LocalDateTime.now());
        approvalRecord.setApprovalReason(leaveApplyApprove.getApprovalReason());
        approvalRecord.setProcessInstanceId(leaveApplyApprove.getProcessInstanceId());
        try {
            String processInstanceId = leaveApplyApprove.getProcessInstanceId();
            String approverId = leaveApplyApprove.getApproverId();
            // TODO 根据流程id，任务id，审批人，查询任务
            Task task = CamundaUtils.getCurrentTask(processInstanceId,approverId);
            if (task != null && approverId.equals(task.getAssignee())) {
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, Object> applyVariables = objectMapper.convertValue(leaveApplyApprove,Map.class);
                CamundaUtils.completeTask(task.getId(), applyVariables);
                approvalRecord.setEventName(task.getName());
                // 更新申请状态
                // QueryWrapper<LeaveApply> wrapper = new QueryWrapper<>();
                // wrapper.eq("process_instance_id", processInstanceId);
                // LeaveApply leaveApply = leaveApplyMapper.selectOne(wrapper);
                // if (leaveApply != null) {
                //     leaveApply.setStatus("审批中");
                //     leaveApplyMapper.update(leaveApply, wrapper);
                // }
            } else {
                throw new CamundaProcessException(400, "当前无待审批任务或审批人不匹配");
            }
        } catch (CamundaProcessException e) {
            log.error(e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("同意申请失败", e);
            throw new CamundaProcessException(500, "同意申请失败，请稍后重试");
        }

        approvalRecordRepo.create(approvalRecord);

        return DomainResponse.ok();
    }

    // public DomainResponse<Void> reject(String processInstanceId, String approverId, String reason) {
    //     try {
    //         Task task = CamundaUtils.getCurrentTask(processInstanceId);
    //         if (task != null && approverId.equals(task.getAssignee())) {
    //             Map<String, Object> variables = new HashMap<>();
    //             variables.put("approved", false);
    //             variables.put("reason", reason);
    //             CamundaUtils.completeTask(task.getId(), variables);
    //
    //             // 更新申请状态
    //             // QueryWrapper<LeaveApply> wrapper = new QueryWrapper<>();
    //             // wrapper.eq("process_instance_id", processInstanceId);
    //             // LeaveApply leaveApply = leaveApplyMapper.selectOne(wrapper);
    //             // if (leaveApply != null) {
    //             //     leaveApply.setStatus("已驳回");
    //             //     leaveApplyMapper.update(leaveApply, wrapper);
    //             // }
    //         } else {
    //             throw new CamundaProcessException(400, "当前无待审批任务或审批人不匹配");
    //         }
    //     } catch (CamundaProcessException e) {
    //         log.error(e.getMessage());
    //         throw e;
    //     } catch (Exception e) {
    //         log.error("驳回申请失败", e);
    //         throw new CamundaProcessException(500, "驳回申请失败，请稍后重试");
    //     }
    //     return DomainResponse.ok();
    // }
    //
    // public DomainResponse<Void> withdraw(String processInstanceId) {
    //     try {
    //         CamundaUtils.terminateProcessInstance(processInstanceId, "申请人撤回申请");
    //
    //         // 更新申请状态
    //         QueryWrapper<LeaveApply> wrapper = new QueryWrapper<>();
    //         wrapper.eq("process_instance_id", processInstanceId);
    //         LeaveApply leaveApply = leaveApplyRepo.selectOne(wrapper);
    //         if (leaveApply != null) {
    //             leaveApply.setStatus("已撤回");
    //             leaveApplyMapper.update(leaveApply, wrapper);
    //         }
    //     } catch (Exception e) {
    //         log.error("申请人撤回申请失败", e);
    //         throw new CamundaProcessException(500, "撤回申请失败，请稍后重试");
    //     }
    //     return DomainResponse.success();
    // }
    //
    // public ApiResult<LeaveApplyVO> resubmit(String processInstanceId, LeaveApplyDTO dto) {
    //     try {
    //         // 终止原流程
    //         CamundaUtils.terminateProcessInstance(processInstanceId, "申请人重新提交申请");
    //
    //         // 删除原申请记录
    //         QueryWrapper<LeaveApply> wrapper = new QueryWrapper<>();
    //         wrapper.eq("process_instance_id", processInstanceId);
    //         leaveApplyMapper.delete(wrapper);
    //
    //         // 重新发起申请
    //         return ApiResult.success(apply(dto).getData());
    //     } catch (Exception e) {
    //         log.error("申请人重新提交申请失败", e);
    //         throw new CamundaProcessException(500, "重新提交申请失败，请稍后重试");
    //     }
    // }

    public DomainResponse<Deployment> deployLeaveProcess() {
        // 请假流程bpmn路径
        String bpmnName = LeaveApplyConstants.processTypeEnum.APPLY_LEAVE.getBpmnName();
        String busName = LeaveApplyConstants.processTypeEnum.APPLY_LEAVE.getDesc();
        String bpmnPath = StrUtil.format("{}/{}",LeaveApplyConstants.bpmnPath,bpmnName);
        // 部署启动流程
        Deployment deployment = CamundaUtils.deployProcessByClasspath(busName, bpmnPath);
        return DomainResponse.ok(deployment);
    }
}
